﻿using System;
using System.Collections;
using System.ComponentModel.Design;
using System.Windows.Forms.Design;
using Microsoft.WowAddonStudio.FrameXml.Serialization.LayoutFrames;

namespace Microsoft.WowAddonStudio.FrameXml.Components.Designers
{
	/// <summary>
	/// Extends the design mode behavior of a System.Windows.Forms.Control.
	/// </summary>
	public class LayoutFrameControlDesigner : ControlDesigner, ILayoutFrameDesignerEvents
	{
        /// <summary>
        /// Occurs when [initialized new component].
        /// </summary>
        public event EventHandler<FrameDesignerEventArgs> InitializedNewComponent;

		/// <summary>
		/// Initializes a newly created component.
		/// </summary>
		/// <param name="defaultValues">
		/// A name/value dictionary of default values to apply to properties.
		/// May be null if no default values are specified.
		/// </param>
		public override void InitializeNewComponent(IDictionary defaultValues)
		{
			base.InitializeNewComponent(defaultValues);

            if (InitializedNewComponent != null)
                InitializedNewComponent(this, new FrameDesignerEventArgs(Control));
		}

		/// <summary>
		/// Releases the unmanaged resources used by the <see cref="T:System.Windows.Forms.Design.ParentControlDesigner"/>, and optionally releases the managed resources.
		/// </summary>
		/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
		protected override void Dispose(bool disposing)
		{
			try
			{
				//Detach all subscribed event handlers.
                InitializedNewComponent = null;
			}
			finally
			{
				base.Dispose(disposing);
			}
		}

        /// <summary>
        /// Indicates if this designer's control can be parented by the control of the specified designer.
        /// </summary>
        /// <param name="parentDesigner">The <see cref="T:System.ComponentModel.Design.IDesigner"/> that manages the control to check.</param>
        /// <returns>
        /// true if the control managed by the specified designer can parent the control managed by this designer; otherwise, false.
        /// </returns>
        public override bool CanBeParentedTo(IDesigner parentDesigner)
        {
            var component = (IFrameXmlComponent)this.Control;

            if (component.SerializationObject is LayoutFrame)
            {
                var layoutFrame = (LayoutFrame)component.SerializationObject;

                if (layoutFrame.Virtual)
                    return false;
            }

            return base.CanBeParentedTo(parentDesigner);
        }

        /// <summary>
        /// Gets a list of <see cref="T:System.Windows.Forms.Design.Behavior.SnapLine"/> objects representing significant alignment points for this control.
        /// </summary>
        /// <value></value>
        /// <returns>
        /// A list of <see cref="T:System.Windows.Forms.Design.Behavior.SnapLine"/> objects representing significant alignment points for this control.
        /// </returns>
        public override IList SnapLines
        {
            get
            {
                if (!CanParent())
                    return new Array[0];

                return base.SnapLines;
            }
        }

        /// <summary>
        /// Determines whether [is root parent virtual].
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if [is root parent virtual]; otherwise, <c>false</c>.
        /// </returns>
        private bool CanParent()
        {
            bool canParent = true;

            var component = (IFrameXmlComponent)this.Control;

            if (component != null)
            {
                while (component.Name != "Ui")
                {
                    var layoutFrame = (LayoutFrame)component.SerializationObject;

                    if (layoutFrame != null)
                    {
                        if (layoutFrame.LayoutHidden || layoutFrame.Locked)
                        {
                            canParent = false;
                            break;
                        }
                    }

                    component = component.Parent;
                }
            }

            return canParent;
        }
	}
}